package com.email.crontab.common.service.impl;

import com.beust.jcommander.internal.Maps;
import com.email.crontab.common.dao.JobDao;
import com.email.crontab.common.domain.JobDO;
import com.email.crontab.common.service.JobService;
import com.email.crontab.framework.config.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;


@Slf4j
@Service
public class JobServiceImpl implements JobService {
    @Autowired
    private JobDao jobDao;
    @Autowired
    private Scheduler myScheduler;

    @Override
    public JobDO get(Long id) {
        return jobDao.get(id);
    }

    @Override
    public List<JobDO> list(Map<String, Object> map) {
        return jobDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return jobDao.count(map);
    }

    @Override
    public int save(JobDO job) {
        addJob(job.getJobClassName(),job.getCronExpression(),job.getParameter());
        return jobDao.save(job);
    }

    @Override
    public int update(JobDO job) {
        deleteJob(job.getJobClassName());
        addJob(job.getJobClassName(),job.getCronExpression(),job.getParameter());
        job.setStatus(CommonConstant.TASK_MNORMAL);
        return jobDao.update(job);
    }

    @Override
    public int updateAll(JobDO job) {
        return jobDao.updateAll(job);
    }

    @Override
    public int remove(Long id) {
        return jobDao.remove(id);
    }

    @Override
    public int batchRemove(Long[] ids) {
        return jobDao.batchRemove(ids);
    }

    @Override
    public Map<String, Object> getById(Long id) {
        JobDO job = jobDao.get(id);
        Map<String, Object> result = Maps.newHashMap();
        if (job !=null){
            result.put("data",job);
            return result;
        }
        return result;
    }

    /**
     * 添加定时任务
     */
    @Override
    public void addJob(String jobClassName, String cronExpression, String parameter){

        try {
            // 启动调度器
            myScheduler.start();

            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
                    .withIdentity(jobClassName)
                    .usingJobData("parameter", parameter)
                    .build();

            //表达式调度构建器(即任务执行的时间) 使用withMisfireHandlingInstructionDoNothing() 忽略掉调度暂停过程中没有执行的调度
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName)
                    .withSchedule(scheduleBuilder).build();

            myScheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error(e.getMessage());
            log.error("创建定时任务失败");
        } catch (Exception e){
            log.error("后台找不到该类名任务");
        }
    }

    /**
     * 删除定时任务
     */
    @Override
    public void deleteJob(String jobClassName){

        try {
            myScheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
            myScheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
            myScheduler.deleteJob(JobKey.jobKey(jobClassName));
        } catch (Exception e) {
            log.error("删除定时任务失败");
        }
    }

    @Override
    public void pauseJob(Long id) {
        JobDO job = get(id);
        if(job == null){
            return ;
        }
        try {
            myScheduler.pauseJob(JobKey.jobKey(job.getJobClassName()));
        } catch (SchedulerException e) {
            log.error("暂停定时任务失败");
        }
        job.setStatus(CommonConstant.TASK_DISABLE);
        jobDao.update(job);
    }

    @Override
    public void resumeJob(Long id) {
        JobDO job = get(id);
        if(job == null){
            return;
        }
        try {
            myScheduler.resumeJob(JobKey.jobKey(job.getJobClassName()));
        } catch (SchedulerException e) {
            log.error("恢复定时任务失败");
        }
        job.setStatus(CommonConstant.TASK_MNORMAL);
       jobDao.update(job);
    }

    public static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job)class1.newInstance();
    }

}
